package com.hzy.admin.services.system.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzy.admin.framework.JwtTokenUtil;
import com.hzy.admin.framework.MessageBox;
import com.hzy.admin.configs.AppConfigs;
import com.hzy.admin.models.vo.system.*;
import com.hzy.admin.services.system.ISysRoleService;
import com.hzy.admin.services.system.ISysUserRoleService;
import com.hzy.admin.services.system.ISysUserService;
import com.hzy.admin.repository.entity.system.SysRole;
import com.hzy.admin.repository.entity.system.SysUser;
import com.hzy.admin.repository.entity.system.SysUserRole;
import com.hzy.admin.repository.mapper.system.ISysUserMapper;
import com.hzy.toolkit.Tools;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 * +
 *
 * @author hzy
 * @since 2020-04-26
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<ISysUserMapper, SysUser> implements ISysUserService {
    private final HttpServletRequest request;
    private final AppConfigs appConfigs;
    private UserInfoVo info = null;
    private final ISysUserRoleService sysUserRoleService;
    private final ISysRoleService sysRoleService;

    public SysUserServiceImpl(HttpServletRequest request, AppConfigs appConfigs, ISysUserRoleService sysUserRoleService,
                              ISysRoleService sysRoleService) {
        this.request = request;
        this.appConfigs = appConfigs;
        this.info = null;
        this.sysUserRoleService = sysUserRoleService;
        this.sysRoleService = sysRoleService;
    }

    /**
     * 查找列表
     *
     * @param page
     * @param size
     * @param search
     * @return
     */
    @Override
    public TableVo<Map<String, Object>> findList(Integer page, Integer size, SysUser search) {
        Page<Map<String, Object>> iPage = new Page<>(page, size);
        List<Map<String, Object>> data = this.baseMapper.getList(iPage, search);
        return TableVo.page(iPage, data);
    }

    /**
     * 根据 id 查询表单数据
     *
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> findForm(String id) {
        Map<String, Object> map = new HashMap<String, Object>();

        SysUser form = this.baseMapper.selectById(id);
        List<String> roleIds = this.sysUserRoleService.lambdaQuery()
                .eq(SysUserRole::getUserId, id)
                .select(SysUserRole::getRoleId)
                .list()
                .stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toList());

        List<SysRole> allRoleList = this.sysRoleService.lambdaQuery()
                .orderByAsc(SysRole::getNumber)
                .select(SysRole::getId, SysRole::getNumber, SysRole::getName)
                .list();

        map.put("id", id);
        map.put("form", Tools.nullSafe(form, new SysUser()));
        map.put("roleIds", roleIds);
        map.put("allRoleList", allRoleList);
        return map;
    }

    /**
     * 保存数据
     *
     * @param form
     * @return
     */
    @Override
    @Transactional
    public String saveForm(SysUserVo form) {
        SysUser model = form.getForm();
        List<String> roleIds = form.getRoleIds();

        // 如果是新增
        if (ObjectUtils.isEmpty(model.getId())) {
            if (ObjectUtils.isEmpty(model.getPassword())) {
                model.setPassword("123456");
            }
        } else {
            if (ObjectUtils.isEmpty(model.getPassword())) {
                SysUser oldUser = this.baseMapper.selectById(model.getId());
                model.setPassword(oldUser.getPassword());
            }
        }

        boolean isSuccess = this.saveOrUpdate(model);

        if (!isSuccess) {
            MessageBox.show("操作失败!");
        }

        // 操作角色表
        if (roleIds.size() > 0) {
            List<SysUserRole> oldUserRoleList = this.sysUserRoleService.lambdaQuery()
                    .eq(SysUserRole::getUserId, model.getId())
                    .list();

            isSuccess = this.sysUserRoleService
                    .remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, model.getId()));
            for (String item : roleIds) {
                SysUserRole userRole = oldUserRoleList.stream()
                        .filter(w -> w.getRoleId().equals(item))
                        .findFirst()
                        .orElse(null);

                SysUserRole newUserRole = new SysUserRole();
                newUserRole.setId(userRole == null ? Tools.getUUID() : userRole.getId());
                newUserRole.setUserId(model.getId());
                newUserRole.setRoleId(item);
                this.sysUserRoleService.save(newUserRole);
            }
        }

        return model.getId();
    }

    /**
     * 删除
     *
     * @param ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteList(List<String> ids) {
        for (String item : ids) {
            SysUser user = this.baseMapper.selectById(item);
            if (user.getIsDelete() != 1) {
                MessageBox.show("该信息不能删除！");
            }
            this.sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, item));
            this.removeById(item);
        }
    }

    /**
     * 检查账户信息
     *
     * @param authUserDto
     * @return
     */
    @Override
    public String check(AuthUserVo authUserDto) {

        if (Strings.isEmpty(authUserDto.getUserName())) {
            MessageBox.show("请输入 账户名称!");
        }

        if (Strings.isEmpty(authUserDto.getUserPassword())) {
            MessageBox.show("请输入 账户密码!");
        }

        SysUser sysUser = this.lambdaQuery().eq(SysUser::getLoginName, authUserDto.getUserName()).one();

        if (sysUser == null) {
            MessageBox.show("账户不存在!");
        }

        // 判断密码
        if (!sysUser.getPassword().equals(authUserDto.getUserPassword())) {
            MessageBox.show("账户密码错误!");
        }

        // Jwt （30L * 1000L * 60L） 30分钟
        return JwtTokenUtil.sign(sysUser, (60L * 1000L * 60L) * 2);
    }

    /**
     * 获取 token
     *
     * @return
     */
    @Override
    public String getToken() {
        return this.request.getHeader("Authorization");
    }

    /**
     * 获取账户信息
     *
     * @return
     */
    @Override
    public UserInfoVo getUserInfo() {
        String tokenValue = this.getToken();
        if (Strings.isEmpty(tokenValue)) {
            return null;
        }

        // 验证 token 是否有效
        SysUser sysUser = null;
        try {
            sysUser = JwtTokenUtil.unsign(tokenValue, SysUser.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //如果用户信息一直没变则返回当前
        if (this.info != null && this.info.getUserId().equals(sysUser.getId())) {
            return this.info;
        }

        // 查询 角色 集合
        List<String> list = this.sysUserRoleService.lambdaQuery()
                .eq(SysUserRole::getUserId, sysUser.getId())
                .select(SysUserRole::getRoleId)
                .list()
                .stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toList());

        // 是否超级管理员角色
        boolean isAdministrator = list.contains(this.appConfigs.adminRoleId);

        // 组合账户信息
        this.info = new UserInfoVo(sysUser.getName(), list, sysUser.getId(), isAdministrator, sysUser);
        this.info.setAppTitle(this.appConfigs.title);
        return this.info;
    }

    /**
     * 设置 账户信息
     *
     * @param info
     */
    @Override
    public void setUserInfo(UserInfoVo info) {
        this.info = info;
    }

    /**
     * 修改密码
     */
    @Override
    public void changePassword(UpdatePasswordVo dto) {

        if (ObjectUtils.isEmpty(dto.getOldPwd())) {
            MessageBox.show("旧密码不能为空！");
        }

        if (ObjectUtils.isEmpty(dto.getNewPwd())) {
            MessageBox.show("新密码不能为空！");
        }

        if (ObjectUtils.isEmpty(dto.getQrPwd())) {
            MessageBox.show("确认密码不能为空！");
        }

        if (!dto.getNewPwd().equals(dto.getQrPwd())) {
            MessageBox.show("两次密码不一致！");
        }

        SysUser sysUser = this.baseMapper.selectById(this.info.getUserId());
        if (!dto.getOldPwd().equals(sysUser.getPassword())) {
            MessageBox.show("旧密码不正确！");
        }

        sysUser.setPassword(dto.getNewPwd());
        this.updateById(sysUser);
    }

}
